#pragma once

#include <metalc/block/cobj/cobj_in.h>
#include <metalc/block/cobj/cobj_extord.h>

// #include <dinfra/list.h>
// #include <metalc/base_mlcc.h>

// /* 对于边界的怎么处理?(另外一种方式：两边弄个sentry)第一个内存块也是tlsf管理数据结构，第二个内存块 */
// /* 
// +-------+-----------+---+
// | tlsf  |  free ....| s |
// +-------+-----------+---+
// */



// // #include <dbg/assert.h>
// // 两种访问方式
// // 一种在本节点维持prev和next两个节点的使用情况,一旦节点被使用需要向下一个节点以及上一个节点广播自己的使用状态
// // 该方式在分配时至少存在两次cache misses, 在合并时有1次cache misses(仅向前合并需要一次cache misses),尝试失败不存在任何cache misses

// // 一种是在本节点维持prev指针,next节点使用情况\本节点的使用状况, 一旦节点被使用,需要通知自己的prev节点的使用情况
// // 分配时至少一次cache misses(修改prev节点), 在合并时有一次cache-misses(向前合并仅需要一次cache misses),尝试失败时存在cache misses

// // try merge next
// // next node and next's next node's ptr (2 cache miss)
// // try merge prev
// // prev node (1 cache misses)

// // free
// // set next, prev in used
// #define PREV_COBJ_MASK (1UL)

// // 使用一位标记下面不可用
// typedef struct coalesced_obj{
//     size_t size;
//     // 最后一位表示remote freed
//     struct coalesced_obj *prev_cobj;

//     dlist_t node;
// } cobj_t;


// SAI const word_t cobj_size_bitmask()
// {
//     return 0x7UL;
// }
// SAI const word_t cobj_freed_bit()
// {
//     return 0x2UL;
// }
// SAI const word_t cobj_next_unavail_bit()
// {
//     return 0x1UL;
// }
// SAI const word_t cobj_prev_freed_bit()
// {
//     return 0x4UL;
// }

// SAI bool_t cobj_next_unavail(cobj_t *c)
// {
//     return c->size & cobj_next_unavail_bit();
// }

// SAI __attribute__((const)) word_t cobj_used_hdr_len()
// {
//     return sizeof(cobj_t) - sizeof(dlist_t);
// }

// SAI word_t cobj_get_size(cobj_t *c)
// {
//     return (c->size & (~cobj_size_bitmask()));
// }

// SAI bool_t cobj_is_boundary(cobj_t *prev, cobj_t *c)
// {

//     // if (cobj_get_size(c) == cobj_used_hdr_len())
//     // {
//     //     return TRUE;
//     // }
//     // return FALSE;

//     if (cobj_next_unavail(prev))
//         return TRUE;
//     return FALSE;
// }

// SAI word_t cobj_availsize_to_size(word_t availsize)
// {
//     return availsize + cobj_used_hdr_len();
// }
// SAI word_t cobj_calc_availsize(word_t size)
// {
//     return size - cobj_used_hdr_len();
// }
// SAI word_t cobj_get_availsize(cobj_t *c)
// {
//     return cobj_calc_availsize(cobj_get_size(c));
// }

// SAI bool_t cobj_is_prev_freed(cobj_t *c)
// {
//     return c->size & cobj_prev_freed_bit();
// }
// SAI bool_t cobj_is_freed(cobj_t *c)
// {
//     return c->size & cobj_freed_bit();
// }

// SAI void cobj_set_prev(cobj_t *c, cobj_t *prev)
// {
//     c->prev_cobj = prev;
// }

// SAI cobj_t *cobj_get_prev(cobj_t *c)
// {
//     return (cobj_t *)((word_t)c->prev_cobj & (~PREV_COBJ_MASK));
// }

// SAI cobj_t *cobj_get_next(cobj_t *c)
// {
//     // 如果next不可用返回空
//     if (!cobj_next_unavail(c))
//         return (cobj_t *)((word_t)c + cobj_get_size(c));
//     return NULL;

// }

// SAI bool_t cobj_can_split(cobj_t *c, word_t size)
// {
//     // SASSERT(size >= sizeof(cobj_t));
//     if (cobj_get_size(c) >= size + sizeof(cobj_t))
//         return TRUE;
//     return FALSE;
// }

// SAI cobj_t *cobj_link_next(cobj_t *c)
// {
//     cobj_t *next = cobj_get_next(c);
//     if (next)
//         cobj_set_prev(next, c);
//     return next;
// }

// SAI void cobj_mark_free(cobj_t *c)
// {
//     // relay to next
//     cobj_t *next = cobj_link_next(c);
//     // set free_bit
//     if (next)
//         next->size |= cobj_prev_freed_bit();
//     //else debug_fprintf(stderr, "why next reachable%p\n",c);
//     c->size |= cobj_freed_bit();
// }
// SAI void cobj_mark_used(cobj_t *c)
// {
//     // relay to next
//     cobj_t *next = cobj_get_next(c);
//     //
//     if (next)
//         next->size &= ~cobj_prev_freed_bit();
//     // set free_bit
//     c->size &= ~cobj_freed_bit();
// }

// // this does not change the prev_freed and freed bitflag
// SAI void cobj_set_size(cobj_t *c, word_t new_size)
// {
//     word_t old_size = c->size;
//     //c->obj.size = new_size | (old_size & cobj_size_bitmask());
//     c->size = new_size | (old_size & cobj_size_bitmask());
// }

// SAI cobj_t *cobj_init(void *ptr, word_t size, bool_t is_prev_freed)
// {
//     cobj_t *ret = (cobj_t *)ptr;
//     word_t flag = cobj_freed_bit();
//     if (is_prev_freed)
//         flag |= cobj_prev_freed_bit();
//     ret->size = size | flag;
//     return ret;
// }

// // SAI cobj_t *__cobj_carve_hd(cobj_t *c, word_t old_size, word_t new_size){
// //     // assert(new_size < old_size);
// //     cobj_t *objnew = (cobj_t *)((word_t)c + new_size);
// //     // set_mobjsize(&c->obj, new_size);
// //     c->size = new_size;
// //     // set_mobjsize(&new->obj, old_size - new_size);
// //     objnew->size = old_size - new_size;
// //     return objnew;
// // }
// // 取左边
// SAI cobj_t *cobj_carve_hd(cobj_t *c, word_t new_size)
// {
//     cobj_t *cnew;
//     word_t size = cobj_get_size(c);
//     if (!cobj_can_split(c, new_size)){
//         fatal("can not split [%p, %lx] into %lx\n", c, size,  new_size);
//         return NULL;
//     }

//     word_t remain_size = size - new_size;

//     word_t next_unavail = cobj_next_unavail(c);
//     // set old c
//     cobj_set_size(c, new_size);
//     c->size &= ~cobj_next_unavail_bit();
//     // initialize new cobj, the prev should be
//     cnew = cobj_init((void *)cobj_get_next(c), remain_size, FALSE);

//     cnew->size |= next_unavail;
//     // set new cobj
//     cobj_mark_free(cnew);
//     // set next->prev to new cobj

//     // set new_avail
//     // fatal("split [%p, %lx] into [%p, %lx] and [%p, %lx], prev %lx\n", c, size, c, get_mobjsize(&c->obj), cnew, get_mobjsize(&new->obj), cobj_get_prev(new));
//     return new;
// }

// // 取右边
// SAI cobj_t *cobj_carve_tl(cobj_t *c, word_t new_size)
// {
//     cobj_t *cnew;
//     word_t size = cobj_get_size(c);
//     if (!cobj_can_split(c, new_size))
//         return NULL;

//     word_t remain_size = size - new_size;

//     word_t next_unavail = cobj_next_unavail(c);
//     // set old c
//     cobj_set_size(c, remain_size);
//     c->size &= ~cobj_next_unavail_bit();
//     // initialize new cobj, the prev should be
//     cnew = cobj_init((void *)cobj_get_next(c), new_size, TRUE);

//     cnew->size |= next_unavail;
//     // set new cobj
//     cobj_mark_free(c);
//     // set next->prev to new cobj

//     // set new_avail

//     return cnew;
// }


// // 取右边
// // SAI cobj_t *cobj_carve_tl(cobj_t *c, word_t new_size)
// // {
// //     cobj_t *new;
// //     word_t size = cobj_get_size(c);
// //     if (!cobj_can_split(c, new_size))
// //         return NULL;

// //     word_t remain_size = size - new_size;
// //     // set old c
// //     cobj_set_size(c, remain_size);
// //     // initialize new cobj, the prev should be
// //     new = cobj_init((void *)cobj_get_next(c), new_size, FALSE);
// //     // set new cobj
// //     cobj_mark_free(c);
// //     // set next->prev to new cobj
// //     return new;
// // }

// // to
// SAI cobj_t *cobj_set_boundary(void *ptr)
// {
//     cobj_t *ret = (cobj_t *)ptr;
//     ret->size = 0;
//     cobj_set_size(ret, cobj_used_hdr_len());
//     return ret;
// }

// SAI cobj_t *cobj_create_boundary(cobj_t *c)
// {
//     // cobj_set_size(c, cobj_get_size(c) - cobj_used_hdr_len());

//     // // TODO: try
//     // cobj_t *boundary = cobj_set_boundary(cobj_get_next(c));

//     // //boundary->obj.size &= ~cobj_freed_bit();

//     // //cobj_mark_free(c);

//     // return c;

//     // // ret->is_freed = FALSE;
//     // // ret->prev_freed = FALSE;

//     //cobj_set_size(c, cobj_get_size(c) - cobj_used_hdr_len());
//     c->size |= cobj_next_unavail_bit();

//     return c;
// }

// SAI cobj_t *cobj_extend_boundary(cobj_t *c, word_t size)
// {
//     cobj_t *next;
//     // extend the boundary

//     // if (!cobj_is_boundary(c, NULL)&&(cobj_get_size(c) != 0))
//     //     return NULL;

//     // //cobj_set_size(next, cobj_used_hdr_len());
//     // //next->prev_freed = TRUE;
//     // //next->is_freed = TRUE;
//     // cobj_set_size(c, size);

//     // next = cobj_get_next(c);
//     // next->obj.size = cobj_used_hdr_len();

//     // cobj_mark_free(c);

//     if (!cobj_is_boundary(c, NULL) && (cobj_get_size(c) != 0))
//         return NULL;

//     //cobj_set_size(next, cobj_used_hdr_len());
//     //next->prev_freed = TRUE;
//     //next->is_freed = TRUE;
//     //cobj_set_size(c, size);
//     //c->obj.size &= ~cobj_next_unavail_bit();
//     //next = cobj_get_next(c);

//     cobj_set_size(c, cobj_get_size(c)+size);
//     //next->obj.size |= cobj_next_unavail_bit();
//     cobj_mark_free(c);

//     return c;
// }

// SAI cobj_t *__cobj_append(cobj_t *prev, cobj_t *next){
//     prev->size += cobj_get_size(next);
//     return prev;
// }

// SAI cobj_t *cobj_append(cobj_t *prev, cobj_t *next)
// {
//     // assert_eq(cobj_get_next(prev) == next);
//     // if(cobj_get_next(prev) != next){
//     //     printf("%p, %p",cobj_get_next(prev), next);
//     // }
//     if (cobj_is_boundary(prev, next)){
//         return NULL;
//         //abort();
//     }
    
//     // debug_fprintf(stderr, "merged [%p, %lx] and [%p, %lx], prev %lx\n", prev, get_mobjsize(&prev->obj), next, get_mobjsize(&next->obj), cobj_get_prev(next));

//     // assert(cobj_is_freed(prev) && cobj_is_freed(next));
//     prev->size += cobj_get_size(next);
//     prev->size |= cobj_next_unavail(next);
//     cobj_link_next(prev);
//     // debug_fprintf(stderr, "get merged block [%p, %lx]\n", prev, get_mobjsize(&prev->obj));
//     return prev;
// }
// // 获得之前的

// // 获得之后的

// // 使用一位标记下面不可用
// typedef struct coalesced_obj{
//     size_t size_state; /* 后三位表示 */
//     // 最后一位表示remote freed
//     struct coalesced_obj *prev_cobj;

//     dlist_t node;
// } cobj_t;

// /* 这个只用于分割合并式的 */
// /* size表示next的偏移自身free状态() size     | freed */
// /* prev表示prev的位置及free状态() prev_ptr | prev_freed */
// /* init (ptr, size, &sentry) -> blk 接受一个ptr, size, 初始化成一个块 + sentry块 */
// /* try_append(pblk, nblk) -> blk 合并临近blk，非相邻返回空 */
// /* try_split(oblk, size, &nblk)-> blk 分割blk, 返回前面的, 同时将下一块写入nblk. 如果nblk为空说明切不出来 */

// /* 分割后不设置状态 */
// SAI size_t cobj_sizeof(cobj_t *blk){
//     return blk->size_state & (~1UL);
// }
// SAI __attribute__((const)) size_t cobj_hdr_len(){
//     return sizeof(cobj_t) - sizeof(dlist_t);
// }
// SAI cobj_t *__cobj_split(cobj_t *blk, size_t tsize){
//     size_t size = cobj_sizeof(blk);
//     blk->size_state = tsize; /* 清除 used state */
//     next_blk->size_state = size - tsize; 
//     next_blk->prev_cobj = blk;
//     return 
// }
// SAI cobj_t *cobj_init(void *ptr, size_t size, cobj_t **sentry){
    
// }